/*Copyright (c) 2009 Michael Streif
 *
 *Permission is hereby granted, free of charge, to any person obtaining a copy
 *of this software and associated documentation files (the "Software"), to deal
 *in the Software without restriction, including without limitation the rights
 *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *copies of the Software, and to permit persons to whom the Software is
 *furnished to do so, subject to the following conditions:
 *
 *The above copyright notice and this permission notice shall be included in
 *all copies or substantial portions of the Software.
 *
 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *THE SOFTWARE.
 */

#include "pic.h"
#include "asm.h"

// ports of the two PICs
#define PIC1		0x20		// IO base address for master PIC
#define PIC2		0xA0		// IO base address for slave PIC
#define PIC1_COMMAND	0x20
#define PIC1_DATA		0x21
#define PIC2_COMMAND    0xA0
#define PIC2_DATA		0xA1

// commands
#define ICW1_ICW4		0x01		// ICW4 (not) needed
#define ICW1_SINGLE	0x02		// Single (cascade) mode
#define ICW1_INTERVAL4	0x04		// Call address interval 4 (8)
#define ICW1_LEVEL	0x08		// Level triggered (edge) mode
#define ICW1_INIT		0x10		// Initialization - required!

#define ICW4_8086		0x01		// 8086/88 (MCS-80/85) mode
#define ICW4_AUTO		0x02		// Auto (normal) EOI
#define ICW4_BUF_SLAVE	0x08		// Buffered mode/slave
#define ICW4_BUF_MASTER	0x0C		// Buffered mode/master
#define ICW4_SFNM		0x10		// Special fully nested (not)

#define PIC_EOI		0x20		// EOI command code

void initPIC(char offset1, char offset2)
{
	// starts the initialization sequence
	outb(PIC1_COMMAND, ICW1_INIT+ICW1_ICW4);
	ioWait();
	outb(PIC2_COMMAND, ICW1_INIT+ICW1_ICW4);
	ioWait();

	// define the PIC vectors
	outb(PIC1_DATA, offset1);
	ioWait();
	outb(PIC2_DATA, offset2);
	ioWait();

	// continue initialization sequence
	outb(PIC1_DATA, 4);
	ioWait();
	outb(PIC2_DATA, 2);
	ioWait();

	outb(PIC1_DATA, ICW4_8086);
	ioWait();
	outb(PIC2_DATA, ICW4_8086);
	ioWait();

	// mask all IRQs
	outb(PIC1_DATA, 0xFF);
	outb(PIC2_DATA, 0xFF);
}

void sendEOI(unsigned char irq)
{
	if(irq >= 8)
		outb(PIC2_COMMAND,PIC_EOI);

	outb(PIC1_COMMAND,PIC_EOI);
}

// masks the IRQs specified by mask1 (PIC 1) and mask 2 (PIC 2)
// bit = 1  -->  mask IRQ
// bit = 0  -->  unmask IRQ
void maskIRQ(unsigned char mask1, unsigned char mask2)
{
	outb(PIC1_DATA, mask1);
	outb(PIC2_DATA, mask2);
}

